#ifndef __OS_CPU_H__
#define __OS_CPU_H__

#ifdef  OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT  extern
#endif

typedef unsigned char  BOOLEAN;
typedef unsigned char  INT8U;
typedef signed   char  INT8S;
typedef unsigned short INT16U;
typedef signed   short INT16S;
typedef unsigned int   INT32U;
typedef signed   int   INT32S;

typedef unsigned int   OS_STK;
typedef unsigned int   OS_CPU_SR;

/********************************************************************************************************
*
* Method #1:  Disable/Enable interrupts using simple instructions.  After critical section, interrupts
*             will be enabled even if they were disabled before entering the critical section.
*
* Method #2:  Disable/Enable interrupts by preserving the state of interrupts.  In other words, if
*             interrupts were disabled before entering the critical section, they will be disabled when
*             leaving the critical section.
*
* Method #3:  Disable/Enable interrupts by preserving the state of interrupts.  Generally speaking you
*             would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then
*             disable interrupts.  'cpu_sr' is allocated in all of uC/OS-II's functions that need to
*             disable interrupts.  You would restore the interrupt disable state by copying back 'cpu_sr'
*             into the CPU's status register.
*
********************************************************************************************************/

#define  OS_CRITICAL_METHOD    3

#if      OS_CRITICAL_METHOD == 2
#define  OS_ENTER_CRITICAL() IRQFIQDE
/* Note: R0 register need not be saved, for it gets saved outside. Refer SDT userguide 6-5 */
#define IRQFIQDE __asm                       \
{                                            \
        mrs r0,CPSR;                         \
        stmfd sp!,{r0};                      \
        orr r0,r0,#NOINT;                    \
        msr CPSR_c,r0;                       \
}

#define  OS_EXIT_CRITICAL() IRQFIQRE
#define IRQFIQRE __asm                       \
{                                            \
        ldmfd sp!,{r0};                      \
        msr CPSR_c,r0;                       \
}
#endif

#if      OS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL()  (cpu_sr = OSCPUSaveSR())
#define  OS_EXIT_CRITICAL()   (OSCPURestoreSR(cpu_sr))
#endif

#define  OS_STK_GROWTH        1 /* from high to low */

#define  OS_TASK_SW()         OSCtxSw()

void UCOS_IRQHandler(void);
void OSCtxSw(void);
void OSIntCtxSw(void);

#if OS_CRITICAL_METHOD == 3
OS_CPU_SR  OSCPUSaveSR(void);
void       OSCPURestoreSR(OS_CPU_SR cpu_sr);
#endif

#endif /*__OS_CPU_H__*/
